#pragma once
#include "NameCreateBase.h"
class CParamBase :public CNameCreateBase
{
public:
	virtual void Write(CStreamSaveData& fp) const {};
	
	virtual int Read(CStreamLoadData &fp) { return 0; };

	virtual ~CParamBase()
	{
	}
};


template<class T>
class CTemplateParam:public CParamBase
{
	template<bool n>
	struct bool_trait { };
public:
	CTemplateParam(const T& data)
	{
		m_strClassName = QString("Param_") + GetTypeName();
		
		if (CObjectCreateFromName::GetInstance()->HasParam(m_strClassName) == false)
		{
			CObjectCreateFromName::GetInstance()->AddParam(m_strClassName, boost::bind(&CTemplateParam<T>::Create));
		}
		SetData(data);
	}
	
	CTemplateParam()
	{
		m_strClassName = QString("Param_") + GetTypeName();
		if (CObjectCreateFromName::GetInstance()->HasParam(m_strClassName) == false)
		{
			CObjectCreateFromName::GetInstance()->AddParam(m_strClassName, boost::bind(&CTemplateParam<T>::Create));
		}
	}

	virtual ~CTemplateParam()
	{
	}

	const T& GetData() const
	{
			return m_data;
	}

	void SetData(const T& data) 
	{
		m_data = data;
	}

	void Write(CStreamSaveData& fp) const
	{
		//fp.Write(m_strClassName);
		fp.Write(GetTypeName());
		fp.Write(m_data);
	}

	int Read(CStreamLoadData &fp)
	{
		//fp.Read(m_strClassName);
		 fp.Read(m_data);
		 return 0;
	}
	
	static CNameCreateBase* Create() 
	{
		CTemplateParam<T>* ret = (new CTemplateParam<T>());
		return (CNameCreateBase*)ret;
	}
private:
	QString GetTypeName() const
	{
		return GetTypeNameCore(bool_trait<has_member_GetTypeName<T>::value>());
	}

	QString GetTypeNameCore(bool_trait<true>) const
	{
		return T::GetTypeName();;
	}

	QString GetTypeNameCore(bool_trait<false>) const
	{
		QString strType = QString(typeid(T).name());
		if (strType == "class QString")
		{
			strType = "QString";
		}
		if (strType.contains("basic_string"))
		{
			strType = "string";
		}
		return strType;
	}
private:
	T m_data;
	QString m_strClassName;
};


